#  Copyright (c) 2006 4ssoM LLC <ed.moss@mac.com>
#  
#  The MIT License
#  
#  Permission is hereby granted, free of charge, to any person obtaining a copy
#  of this software and associated documentation files (the "Software"), to deal
#  in the Software without restriction, including without limitation the rights
#  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#  copies of the Software, and to permit persons to whom the Software is
#  furnished to do so, subject to the following conditions:
#  
#  The above copyright notice and this permission notice shall be included in
#  all copies or substantial portions of the Software.
#  
#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
#  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#  THE SOFTWARE.
#  


require 'dry_scaffold/dry_scaffold'
require 'dry_scaffold/form_options'

module DryScaffold #:nodoc:
  #--
  # The methods to be included in both ApplicationController and ApplicationHelper
  #++

  @where_clause = ''
  @where_values = {}
  @include_values = nil
  # :like, use the sql "Like" form for comparison instead of "=" 
  # :include, add the models to the :include hast. Example: :include => [:client_admin]
  # :sql_function, use this function around the field_name. Example: :sql_function => "LOWER"
  # :compare_with, supply a compare operator "<" or ">" or "<="
  # :restrict, a restrick clause, other clause updates do not update this clause
  def build_clause(model, field_name, field_value, options = {})
    if field_value.nil? or field_value.to_s.empty?
      return
    end
    if @where_clause.nil?
      @where_clause = ''
    else
      @where_clause += ' AND '
    end
    if model.nil?
      key = field_name.to_sym
      column_name = field_name
    else
      key = "#{model.table_name}_#{field_name}".to_sym
      column_name = "#{model.table_name}.#{field_name}"
    end
    key = "restrict_#{key.to_s}".to_sym if options[:restrict]
    #TODO 2006-08-22 Level=1 - Make this a switch in the config, turn on case-insensitive via WHERE
    column_name = "NLS_UPPER(#{column_name})" if 'Oracle' == ActiveRecord::Base.connection.adapter_name
    column_name = "#{options[:sql_function]}(#{column_name})" unless options[:sql_function].nil?
    @where_clause += column_name
    negate = false
    value = String.new(field_value.to_s)
    if !value.sub!("<>", "").nil?
      value.strip!
      negate = true
    end
    if options.has_key?(:like) and options[:like]
      @where_clause += " NOT " if negate
      @where_clause += " LIKE :" + key.to_s
      value = "%" + value + "%"
      value = value.upcase if 'Oracle' == ActiveRecord::Base.connection.adapter_name
    elsif options.has_key?(:compare_with) and options[:compare_with]
      @where_clause += " #{options[:compare_with]} :" + key.to_s
    else
      @where_clause += " = :" + key.to_s
    end
    @where_values ||= {}
    @where_values.update(key => value)
    @include_values ||= []
    @include_values << options[:include] unless options[:include].nil?
  end

  def update_find_params_conditions
    if !@where_clause.nil?
      @find_params.update(:conditions => [@where_clause, @where_values], :include => @include_values)
    end
  end
  
  def form_filter_sort_by(model)
    model.to_s + "_filter_sort_by"
  end

  def sort_limit_field_name(model)
    "#{model}_sort_limit"
  end

  def edit_model_name(model)
    "edit_" + model.to_s
  end

  def like_model_name(model)
    "filter_by_" + model.to_s
  end

  def model_map
    params[:model].to_s.camelize.constantize
  rescue
    params[:controller].to_s.singularize.camelize.constantize
  end

  def parent_model_map
    params[:parent_model].to_s.camelize.constantize
  end

  def sort_field_name(model, column)
    model.to_s + "_" + column.name  
  end

  def sort_limit(model)
    params[sort_limit_field_name(model)] ? params[sort_limit_field_name(model)].to_i : model.default_per_page
  end

  def sort_clause(model)
    clause = ''
    for column in @scaffold_model.scaffold_columns
      if column.sortable && !column.sort_order.nil? && !column.sort_order.empty?
        if model.nil?
          column_name = column.name
        else
          column_name = "#{model.table_name}.#{column.name}"
        end
        clause << "," if clause.length > 0
        clause << column_name + ' ' + column.sort_order
      end
    end 
    clause unless clause.empty?
  end

end
